package ltd.helper;

import java.nio.charset.Charset;
import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * AES对称加密码助手类
 */
public class AESHelper {

	/**
	 * 可替换为以下任意一种算法，同时key值的size相应改变。
	 * DES							密钥大小必须等于56
	 * DESede(TripleDES,就是3DES)		密钥长度必须等于112或168
	 * AES							密钥长度必须等于128，192或256，但192和256位可能不可用
	 * Blowfish						密钥长度必须是8的倍数，只能从32到448的范围内（含）
	 * RC2							密钥大小必须介于40和1024位之间
	 * RC4(ARCFOUR)					密钥大小必须介于40和1024位之间
	 */
	public static final String ALGORITHM = "AES";
	/** 
	 *  填充模式
	 */
	public static final String ALGORITHM_CIPHER = "AES/ECB/ISO10126Padding";
	
	public static final Charset CHARSET = Charset.forName("UTF-8");
	
	/** BASE64解密 */
	public static byte[] decryptBASE64(String key) throws Exception {
		return (new BASE64Decoder()).decodeBuffer(key);
	}

	/** BASE64加密 */
	public static String encryptBASE64(byte[] key) throws Exception {
		return (new BASE64Encoder()).encodeBuffer(key);
	}

	/** 获取密钥 */
	private static Key toKey(byte[] key) {
		SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
		return secretKey;
	}
	
	/** 解密 */
	public static byte[] doDecrypt(String data, String key) {
		try {
			if(key == null || key.isEmpty()){
				return data.getBytes(CHARSET);
			}
			return doDecrypt(data.getBytes(CHARSET), key);
		} catch (Exception e) {
		}
		return null;
	}
	
	/** 解密 */
	public static byte[] doDecrypt(byte[] data, String key) {
		try {
			if(key == null || key.isEmpty()){
				return data;
			}
			//Key k = toKey(decryptBASE64(key));
			Key k = toKey(key.getBytes(CHARSET));
			Cipher cipher = Cipher.getInstance(ALGORITHM_CIPHER);
			cipher.init(Cipher.DECRYPT_MODE, k);
			return cipher.doFinal(data);
		} catch (Exception e) {
			System.err.println("!!!解密操作失败!!!");
			e.printStackTrace();
		}
		return null;
	}
	
	/** 解密 */
	public static String doDecryptStr(String data, String key) {
		try {
			if(key == null || key.isEmpty()){
				return data;
			}
			return doDecryptStr(data.getBytes(CHARSET), key);
		} catch (Exception e) {
		}
		return null;
	}
	
	/** 解密 */
	public static String doDecryptStr(byte[] data, String key) {
		try {
			if(key == null || key.isEmpty()){
				return new String(data, CHARSET);
			}
			//Key k = toKey(decryptBASE64(key));
			Key k = toKey(key.getBytes(CHARSET));
			Cipher cipher = Cipher.getInstance(ALGORITHM_CIPHER);
			cipher.init(Cipher.DECRYPT_MODE, k);
			return new String(cipher.doFinal(data), CHARSET);
		} catch (Exception e) {
			System.err.println("!!!解密操作出错!!!");
			e.printStackTrace();
		}
		return null;
	}
	
	/** 解密 */
	public static byte[] doDecrypt(String data, byte[] key) {
		try {
			if(key == null || key.length == 0){
				return data.getBytes(CHARSET);
			}
			return doDecrypt(data.getBytes(CHARSET), key);
		} catch (Exception e) {
		}
		return null;
	}
	
	/** 解密 */
	public static byte[] doDecrypt(byte[] data, byte[] key) {
		try {
			if(key == null || key.length == 0){
				return data;
			}
			Key k = toKey(key);
			Cipher cipher = Cipher.getInstance(ALGORITHM_CIPHER);
			cipher.init(Cipher.DECRYPT_MODE, k);
			return cipher.doFinal(data);
		} catch (Exception e) {
			System.err.println("!!!解密操作出错!!!");
			e.printStackTrace();
		}
		return null;
	}
	
	/** 解密 */
	public static String doDecryptStr(String data, byte[] key) {
		try {
			if(key == null || key.length == 0){
				return data;
			}
			return doDecryptStr(data.getBytes(CHARSET), key);
		} catch (Exception e) {
		}
		return null;
	}
	
	/** 解密 */
	public static String doDecryptStr(byte[] data, byte[] key) {
		try {
			if(key == null || key.length == 0){
				return new String(data, CHARSET);
			}
			Key k = toKey(key);
			Cipher cipher = Cipher.getInstance(ALGORITHM_CIPHER);
			cipher.init(Cipher.DECRYPT_MODE, k);
			return new String(cipher.doFinal(data), CHARSET);
		} catch (Exception e) {
			System.err.println("!!!解密操作出错!!!");
			e.printStackTrace();
		}
		return null;
	}
	
	/** 加密 */
	public static byte[] doEncrypt(String data, String key) {
		try {
			if(key == null || key.isEmpty()){
				return data.getBytes(CHARSET);
			}
			return doEncrypt(data.getBytes(CHARSET), key);
		} catch (Exception e) {
		}
		return null;
	}
	
	/** 加密 */
	public static byte[] doEncrypt(byte[] data, String key) {
		try {
			if(key == null || key.isEmpty()){
				return data;
			}
			//Key k = toKey(decryptBASE64(key));
			Key k = toKey(key.getBytes(CHARSET));
			Cipher cipher = Cipher.getInstance(ALGORITHM_CIPHER);
			cipher.init(Cipher.ENCRYPT_MODE, k);
			return cipher.doFinal(data);
		} catch (Exception e) {
			System.err.println("!!!加密操作出错!!!");
			e.printStackTrace();
		}
		return null;
	}
	
	/** 加密 */
	public static byte[] doEncrypt(String data, byte[] key) {
		try {
			if(key == null || key.length == 0){
				return data.getBytes(CHARSET);
			}
			return doEncrypt(data.getBytes(CHARSET), key);
		} catch (Exception e) {
		}
		return null;
	}
	
	/** 加密 */
	public static byte[] doEncrypt(byte[] data, byte[] key) {
		try {
			if(key == null || key.length == 0){
				return data;
			}
			Key k = toKey(key);
			Cipher cipher = Cipher.getInstance(ALGORITHM_CIPHER);
			cipher.init(Cipher.ENCRYPT_MODE, k);
			return cipher.doFinal(data);
		} catch (Exception e) {
			System.err.println("!!!加密操作出错!!!");
			e.printStackTrace();
		}
		return null;
	}
	
	/** 生成密钥 */
	public static String initKeyStr(String seed) throws Exception {
		SecureRandom secureRandom = null;

		if (seed != null) {
			secureRandom = new SecureRandom(seed.getBytes(CHARSET));//decryptBASE64(seed)
		} else {
			secureRandom = new SecureRandom();
		}

		KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
		kg.init(128, secureRandom);

		SecretKey secretKey = kg.generateKey();

		return encryptBASE64(secretKey.getEncoded());
	}
	
	/** 生成密钥 */
	public static byte[] initKey(String seed) throws Exception {
		SecureRandom secureRandom = null;

		if (seed != null) {
			secureRandom = new SecureRandom(seed.getBytes(CHARSET));//decryptBASE64(seed)
		} else {
			secureRandom = new SecureRandom();
		}

		KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
		kg.init(128, secureRandom);

		SecretKey secretKey = kg.generateKey();
		
		return secretKey.getEncoded();
	}
}
